
{% macro alt_names(lst=[]) -%}
  {#- add all the names and IPs we know about -#}
  {%- set netiface = salt.caasp_pillar.get('hw:netiface') -%}
  {%- set this_ip = grains['ip4_interfaces'][netiface][0] -%}
  {%- set altNames = [
    "DNS: " + grains['nodename'], "DNS: " + grains['nodename'] + "." + pillar['internal_infra_domain'],
    "DNS: " + grains['machine_id'], "DNS: " + grains['machine_id'] + "." + pillar['internal_infra_domain'],
    "IP: " + this_ip, "DNS: localhost", "IP: 127.0.0.1", "IP: " + salt.caasp_pillar.get('kubernetes:lookup:kube-apiserver:cluster_ip'),
    "IP: " + salt.caasp_pillar.get('kubernetes:lookup:kube-apiserver:PUBLIC_ADDRESS'),
    "IP: " + salt.caasp_pillar.get('kubernetes:lookup:kube-apiserver:extra_ips','127.0.0.1')
  ] -%}
  {#- append all the names/IPs provided (if not empty) -#}
  {%- for name in lst -%}
    {%- if name and name|length > 0 -%}
      {%- if salt['caasp_filters.is_ip'](name) -%}
        {%- do altNames.append("IP: " + name) -%}
      {%- else -%}
        {%- do altNames.append("DNS: " + name) -%}
      {%- endif -%}
    {%- endif -%}
  {%- endfor -%}
  {{ ", ".join(altNames) }}
{%- endmacro %}

#####################################################################

# a list of alternative names for a kubernetes master
{% macro alt_master_names(lst=[]) -%}
  {%- set names_lst = ["kubernetes",
                       "kubernetes.default",
                       "kubernetes.default.svc",
                       "kubernetes.default.svc.cluster",
                       "kubernetes.default.svc.cluster.local",
                       "localhost",
                       "api",
                       "api." + pillar['internal_infra_domain'],
                       salt.caasp_pillar.get('kubernetes:lookup:kube-apiserver:external_fqdn'),
                       salt.caasp_pillar.get('kubernetes:lookup:kube-apiserver:cluster_ip'),
                       salt.caasp_pillar.get('kubernetes:lookup:kube-apiserver:extra_ips', '127.0.0.1'),
                       salt.caasp_pillar.get('kubernetes:lookup:kube-apiserver:PUBLIC_ADDRESS')] +
                       salt.caasp_pillar.get('kubernetes:lookup:kube-apiserver:extra_names', []) +
                       lst -%}
  {#- add some standard extra names from the DNS domain -#}
  {% for server, addr in salt['mine.get']('P@roles:(kube-master|kube-minion|etcd)', 'network.ip_addrs', tgt_type='compound').items() -%}
    {%- do names_lst.append(addr[0]) -%}
  {% endfor %}
  {%- if salt.caasp_pillar.get('dns:domain') -%}
    {%- do names_lst.append("kubernetes.default.svc." + pillar['dns']['domain']) -%}
  {%- endif -%}
  {{ alt_names(names_lst) }}
{%- endmacro %}

#####################################################################

{% macro certs(name, crt, key, cn='', o='', extra_alt_names=None) -%}

{%- if extra_alt_names == None -%}
  {#- calculate automatically the altNames depending on the role -#}
  {%- if ( "kube-master" in salt['grains.get']('roles', []) ) or ("etcd" in salt['grains.get']('roles', [])) -%}
    {%- set extra_alt_names = alt_master_names() -%}
  {%- else -%}
    {%- set extra_alt_names = alt_names() -%}
  {%- endif -%}
{%- endif -%}

{{ key }}:
  x509.private_key_managed:
    - bits: 4096
    - user: root
    - group: root
    - mode: 444
    - require:
      - sls:  cert.require
      - file: /etc/pki

{{ crt }}:
  caasp_retriable.retry:
    - target: x509.certificate_managed
    - ca_server: {{ salt['mine.get']('roles:ca', 'ca.crt', tgt_type='grain').keys()[0] }}
    - signing_policy: minion
    - public_key: {{ key }}
  {%- if cn %}
    - CN: {{ cn|yaml_dquote }}
  {%- else %}
    - CN: {{ ("system:" + name)|yaml_dquote }}
  {%- endif %}
    - C: {{ pillar['certificate_information']['subject_properties']['C']|yaml_dquote }}
    - Email: {{ pillar['certificate_information']['subject_properties']['Email']|yaml_dquote }}
    - GN: {{ pillar['certificate_information']['subject_properties']['GN']|yaml_dquote }}
    - L: {{ pillar['certificate_information']['subject_properties']['L']|yaml_dquote }}
    {# "system:{{ name }}" is a kubernetes specific role identifying a {{ name }} in th system #}
  {%- if o %}
    - O: {{ o|yaml_dquote }}
  {%- else -%}
    - O: {{ ("system:" + name)|yaml_dquote }}
  {%- endif %}
    - OU: {{ pillar['certificate_information']['subject_properties']['OU']|yaml_dquote }}
    - SN: {{ pillar['certificate_information']['subject_properties']['SN']|yaml_dquote }}
    - ST: {{ pillar['certificate_information']['subject_properties']['ST']|yaml_dquote }}
    - basicConstraints: "critical CA:false"
    - keyUsage: "critical digitalSignature, keyEncipherment, dataEncipherment"
    - extendedKeyUsage: "serverAuth, clientAuth"
  {%- if extra_alt_names %}
    - subjectAltName: {{ extra_alt_names|yaml_dquote }}
  {%- endif %}
    - days_valid: {{ pillar['certificate_information']['days_valid']['certificate'] }}
    - days_remaining: {{ pillar['certificate_information']['days_remaining']['certificate'] }}
    - backup: True
    - user: root
    - group: root
    - mode: 644
    - retry:
        attempts: 5
    - require:
      - sls: cert.require
      - x509: {{ key }}

{{ crt }}-bundle:
  file.managed:
    - name: /etc/pki/private/{{ name }}-bundle.pem
    - source: salt://cert/cert-bundle.jinja
    - template: jinja
    - user: root
    - group: root
    - mode: 600
    - makedirs: True
    - context:
        certificate: {{ crt }}
        key:         {{ key }}
    - onchanges:
        - caasp_retriable: {{ crt }}
        - x509: {{ key }}

{%- endmacro %}
